#include "mibs_encrypiton.h"
#include "keyschedule.h"
#include <stdio.h>

void encryption_oneround( nibble round_key[][8] , const int round , nibble instate[] , const int statesize )
{
	nibble leftpart[8] = { 0 } ;
	nibble rightpart[8] = { 0 } ;
	nibble temp[8] = { 0 } ;
	int i = 0 ;
	for ( i = 0 ; i < NIBBLE_NUM/2 ; ++i )
	{
		leftpart[i] = instate[i] ;
		rightpart[i] = instate[i+8] ;
	}
	keyxor( leftpart , round_key[round] , NIBBLE_NUM/2 , leftpart ) ;
	sbox( leftpart , NIBBLE_NUM/2 , leftpart ) ;
  	printf( "\nSbox %d  " , round ) ;
  	for ( i = 0 ; i < NIBBLE_NUM/2 ; ++i )
  	{
  		printf( "%x" , leftpart[i] ) ;
  	}

	linear_mix( leftpart , NIBBLE_NUM/2 , temp ) ;
	player( temp , NIBBLE_NUM/2 , leftpart ) ;
	for ( i = 0 ; i < NIBBLE_NUM/2 ; ++i )
	{
		leftpart[i] = instate[i+8] ^ leftpart[i] ;
		instate[i+8] = instate[i] ;
		instate[i] = leftpart[i] ;
	}
}

void mibs( nibble plaintext[] , word initialkey[] , const int keysie , const int n , nibble ciphertext[] )
{
	int i = 0 ;
	nibble use_key[MIBS_ROUND][8] = { 0 } ;
	keyschedule( initialkey , MIBS_NUM , use_key ) ;
	nibble innerstate[NIBBLE_NUM] = { 0 } ;
	for ( i = 0 ; i < MIBS_NUM ; ++i )
	{
		plaintext[i] = innerstate[i] ;
	}
	for ( i = 0 ; i < MIBS_ROUND ; ++i )
	{
		error_insert( innerstate , NIBBLE_NUM , i ) ;
		encryption_oneround( use_key , i , innerstate , NIBBLE_NUM ) ;
//  		if ( i == MIBS_ROUND-1 )
//  		{
//  			for ( int j = 0 ; j < 8 ; ++j )
//  			{
//  				printf( "%x " , use_key[i][j] ) ;
//  			}
//  		}
	}
	nibble temp[8] = { 0 } ;
	for ( i = 0 ; i < NIBBLE_NUM/2 ; ++i )
	{
		temp[i] = innerstate[i] ;
		innerstate[i] = innerstate[i+8] ;
		innerstate[i+8] = temp[i] ; 
	}
	for ( i = 0 ; i < NIBBLE_NUM ; ++i )
	{
		ciphertext[i] = innerstate[i] ;
	}
}

void xor_error_encryption( error_struct* error_data , nibble plaintext[] , word initialkey[] , const int keysie , const int n , nibble ciphertext[] )
{
	if ( !add_error_struct(error_data) )
	{
		printf( "warning" ) ;
	}
	set_error_insert( error_insert_hook_func ) ;
	mibs( plaintext , initialkey , keysie , n , ciphertext ) ;
}
